﻿#include "SearchService.h"
#include <QDebug>
#include <QStringList>
#include "CodeEditor.h"
#include "PageService.h"

SearchService::SearchService() : QObject(nullptr)
{
	// 初始化默认时间范围（默认搜索近30天）
	m_lastEndTime = QDateTime::currentDateTime();
	m_lastStartTime = m_lastEndTime.addDays(-30);
}

SearchService::~SearchService()
{
	// 注意：m_notification 由外部管理，不在此处删除
}

void SearchService::init()
{
	// 检查数据库表依赖（依赖file_info和recent_item表，与PageService共用）
	qDebug() << "SearchService初始化：检查数据库表依赖";

	// 验证表是否存在（通过查询系统表确认，兼容SQLite）
	QString checkTableSql = R"(
        SELECT name FROM sqlite_master 
        WHERE type='table' AND (name='file_info' OR name='recent_item')
    )";

	DbMgr::GetInstance()->executeSql(checkTableSql, [this](const DbResult& result) {
		if (!result.isSuccess()) {
			qCritical() << "SearchService初始化失败：检查表存在性错误" << result.error();
			emit searchFailed("数据库表依赖检查失败：" + result.error());
			return;
		}

		// 确认两个核心表都存在
		QList<QString> existTables;
		for (const QVariantMap& row : result.data()) {
			existTables.append(row["name"].toString());
		}

		if (!existTables.contains("file_info") || !existTables.contains("recent_item")) {
			qCritical() << "SearchService初始化失败：缺少核心表（file_info/recent_item）";
			emit searchFailed("缺少必要数据库表，无法提供搜索功能");
		}
		else {
			qDebug() << "SearchService初始化成功：表依赖验证通过";
		}
		});
}

void SearchService::setNotification(Notification* notification)
{
	if (!notification) {
		qWarning() << "SearchService::setNotification - notification为空";
		return;
	}

	m_notification = notification;
	qDebug() << "SearchService：Notification已设置";
}

void SearchService::setRecentList(RecentList* recentList)
{
	if (m_recentList) {
		qDebug() << "SearchService：更新RecentList引用";
	}
	m_recentList = recentList;
}

void SearchService::setSearchResultList(SearchResultList* resultList)
{
	m_searchResultList = resultList;
	if (m_searchResultList) {
		// 连接结果列表的点击信号到跳转逻辑
		connect(m_searchResultList, &SearchResultList::resultClicked,
			this, &SearchService::onResultItemClicked);
		qDebug() << "SearchResultList已设置";
	}
}

void SearchService::searchByKeyword(const QString& keyword)
{
	if (!m_recentList) {
		qWarning() << "SearchService：未设置RecentList，无法展示结果";
		emit searchFailed("未绑定结果展示组件（RecentList）");
		return;
	}

	// 缓存关键词
	m_lastKeyword = keyword;
	qDebug() << "SearchService：关键词搜索 - " << keyword;

	// 构建搜索SQL（模糊匹配文件名和文件路径，忽略大小写）
	QString condition;
	if (!keyword.isEmpty()) {
		QString escapedKeyword = keyword;
		condition = QString("(f.file_name LIKE '%%1%' OR f.file_path LIKE '%%1%')")
			.arg(escapedKeyword);
	}

	// 拼接完整SQL（关联表 + 排序 + 限制数量）
	QString sql = QString(R"(
        SELECT r.recent_id, r.file_id, r.access_time, f.file_name, f.file_path
        FROM recent_item r
        JOIN file_info f ON r.file_id = f.file_id
        %1
        ORDER BY r.access_time DESC
        LIMIT 100
    )").arg(condition.isEmpty() ? "" : "WHERE " + condition);

	// 执行搜索并处理结果
	DbMgr::GetInstance()->executeSql(sql, [this](const DbResult& result) {
		handleRecentSearchResult(result);
		});
}

void SearchService::searchByTimeRange(const QDateTime& start, const QDateTime& end)
{
	if (!m_recentList) {
		qWarning() << "SearchService：未设置RecentList，无法展示结果";
		emit searchFailed("未绑定结果展示组件（RecentList）");
		return;
	}

	// 验证时间范围有效性
	if (start > end) {
		qWarning() << "SearchService：时间范围无效（开始时间晚于结束时间）";
		showNotification(Notify_Type_Warning, "搜索参数错误", "开始时间不能晚于结束时间");
		emit searchFailed("时间范围参数无效");
		return;
	}

	// 缓存时间范围
	m_lastStartTime = start;
	m_lastEndTime = end;
	qDebug() << "SearchService：时间范围搜索 - "
		<< start.toString("yyyy-MM-dd HH:mm") << " 至 "
		<< end.toString("yyyy-MM-dd HH:mm");

	// 构建时间条件（SQLite支持ISO格式时间比较）
	QString startIso = start.toString(Qt::ISODate);
	QString endIso = end.toString(Qt::ISODate);
	QString condition = QString("r.access_time BETWEEN '%1' AND '%2'")
		.arg(startIso).arg(endIso);

	// 拼接完整SQL
	QString sql = QString(R"(
        SELECT r.recent_id, r.file_id, r.access_time, f.file_name, f.file_path
        FROM recent_item r
        JOIN file_info f ON r.file_id = f.file_id
        WHERE %1
        ORDER BY r.access_time DESC
        LIMIT 100
    )").arg(condition);

	// 执行搜索并处理结果
	DbMgr::GetInstance()->executeSql(sql, [this](const DbResult& result) {
		handleRecentSearchResult(result);
		});
}

void SearchService::searchCombined(const QString& keyword, const QDateTime& start, const QDateTime& end)
{
	if (!m_recentList) {
		qWarning() << "SearchService：未设置RecentList，无法展示结果";
		emit searchFailed("未绑定结果展示组件（RecentList）");
		return;
	}

	// 验证时间范围
	if (start > end) {
		qWarning() << "SearchService：组合搜索 - 时间范围无效";
		showNotification(Notify_Type_Warning, "搜索参数错误", "开始时间不能晚于结束时间");
		emit searchFailed("时间范围参数无效");
		return;
	}

	// 缓存搜索参数
	m_lastKeyword = keyword;
	m_lastStartTime = start;
	m_lastEndTime = end;
	qDebug() << "SearchService：组合搜索 - 关键词：" << keyword
		<< " 时间范围：" << start.toString("yyyy-MM-dd") << "至" << end.toString("yyyy-MM-dd");

	// 构建组合条件
	QStringList conditions;
	// 1. 时间条件
	QString startIso = start.toString(Qt::ISODate);
	QString endIso = end.toString(Qt::ISODate);
	conditions.append(QString("r.access_time BETWEEN '%1' AND '%2'").arg(startIso).arg(endIso));

	// 2. 关键词条件（可选）
	if (!keyword.isEmpty()) {
		QString escapedKeyword = keyword;
		conditions.append(QString("(f.file_name LIKE '%%1%' OR f.file_path LIKE '%%1%')").arg(escapedKeyword));
	}

	// 拼接完整SQL
	QString sql = QString(R"(
        SELECT r.recent_id, r.file_id, r.access_time, f.file_name, f.file_path
        FROM recent_item r
        JOIN file_info f ON r.file_id = f.file_id
        WHERE %1
        ORDER BY r.access_time DESC
        LIMIT 100
    )").arg(conditions.join(" AND "));

	// 执行搜索并处理结果
	DbMgr::GetInstance()->executeSql(sql, [this](const DbResult& result) {
		handleRecentSearchResult(result);
		});
}

void SearchService::clearSearchResult()
{
	if (m_recentList) {
		m_recentList->clear();
		qDebug() << "SearchService：已清空搜索结果";
		emit searchCompleted(0);
	}
}

QString SearchService::readLineContent(const QString& filePath, int lineNumber)
{
	// 关键修改：使用 TextFileUtils 读取，确保编码处理一致
	bool readOk = false;
	QString content = TextFileUtils::readFile(filePath, TextFileUtils::AUTO_DETECT, &readOk);

	if (!readOk || content.isEmpty()) {
		return "";
	}

	QStringList lines = content.split('\n');

	// lineNumber 从1开始，数组索引从0开始
	if (lineNumber >= 1 && lineNumber <= lines.size()) {
		QString line = lines[lineNumber - 1];
		// 移除可能的 \r
		if (line.endsWith('\r')) {
			line.chop(1);
		}
		return line;
	}

	return "";
}

QList<int> SearchService::searchInFile(const QString& filePath, const QString& searchStr)
{
	QList<int> matchedLines;

	QFile file(filePath);
	if (!file.exists()) {
		qWarning() << "SearchService：文件不存在：" << filePath;
		return matchedLines;
	}

	// 关键修改：使用 TextFileUtils 统一读取，确保编码处理一致
	bool readOk = false;
	QString content = TextFileUtils::readFile(filePath, TextFileUtils::AUTO_DETECT, &readOk);

	if (!readOk || content.isEmpty()) {
		qWarning() << "SearchService：读取文件失败或文件为空：" << filePath;
		return matchedLines;
	}

	// 使用与 readLineContent 相同的分割方式
	QStringList lines = content.split('\n');

	// 逐行搜索并记录行号（行号从1开始）
	for (int i = 0; i < lines.size(); ++i) {
		QString line = lines[i];

		// 移除可能的 \r（Windows 换行符）
		if (line.endsWith('\r')) {
			line.chop(1);
		}

		if (line.contains(searchStr, Qt::CaseInsensitive)) {
			matchedLines.append(i + 1);  // 行号从1开始
		}
	}

	return matchedLines;
}

void SearchService::onResultItemClicked(const QUuid& fileId, int lineNumber)
{
	qDebug() << "点击搜索结果 - 文件ID:" << fileId << "行号:" << lineNumber;

	// 如果是当前文件，直接跳转
	if (fileId == PageService::GetInstance()->getCurrentFileId() || fileId.isNull()) {
		if (auto editor = PageService::GetInstance()->getCodeEditor()) {
			editor->scrollToLine(lineNumber, true);
		}
		return;
	}

	// 如果是其他文件，先打开文件
	QString condition = QString("file_id = '%1'").arg(fileId.toString());
	DbMgr::GetInstance()->select("file_info", "file_path", condition, "",
		[this, lineNumber](const DbResult& result) {
			if (result.isSuccess() && !result.data().isEmpty()) {
				QString filePath = result.data().first()["file_path"].toString();

				// 打开文件后跳转到指定行
				PageService::GetInstance()->openFile(filePath);

				// 延迟跳转，等待文件加载完成
				QTimer::singleShot(300, [lineNumber]() {
					if (auto editor = PageService::GetInstance()->getCodeEditor()) {
						editor->scrollToLine(lineNumber, true);
					}
					});
			}
		});
}

void SearchService::searchInCurrentDoc(const QString& str)
{
	if (!m_searchResultList) {
		qWarning() << "SearchResultList未设置，无法展示搜索结果";
		return;
	}

	if (str.isEmpty()) {
		m_searchResultList->clear();
		emit contentSearchCompleted(0, false);
		return;
	}

	// 关键修改：直接从 CodeEditor 获取当前内容，而不是读取磁盘文件
	CodeEditor* editor = PageService::GetInstance()->getCodeEditor();
	if (!editor) {
		qWarning() << "CodeEditor未设置";
		m_searchResultList->clear();
		emit contentSearchCompleted(0, false);
		return;
	}

	QString currentText = editor->toPlainText();
	if (currentText.isEmpty()) {
		m_searchResultList->clear();
		emit contentSearchCompleted(0, false);
		return;
	}

	// 按行分割内容进行搜索
	QStringList lines = currentText.split('\n');
	QList<int> matchedLines;
	QStringList lineContents;

	for (int i = 0; i < lines.size(); ++i) {
		QString line = lines[i];
		// 移除可能的 \r（Windows 换行符）
		if (line.endsWith('\r')) {
			line.chop(1);
		}

		if (line.contains(str, Qt::CaseInsensitive)) {
			matchedLines.append(i + 1);  // 行号从1开始
			lineContents.append(line);
		}
	}

	int count = matchedLines.size();
	qDebug() << "当前文档搜索完成，找到" << count << "处匹配";

	// 在主线程更新UI
	QMetaObject::invokeMethod(this, [this, matchedLines, lineContents, count]() {
		if (m_searchResultList) {
			m_searchResultList->setSingleFileMode(matchedLines, lineContents);
		}
		emit contentSearchCompleted(count, false);
		}, Qt::QueuedConnection);
}

void SearchService::searchInAllRecents(const QString& str)
{
	if (!m_searchResultList) {
		qWarning() << "SearchResultList未设置";
		return;
	}

	if (str.isEmpty()) {
		m_searchResultList->clear();
		emit contentSearchCompleted(0, true);
		return;
	}

	QString sql = R"(
        SELECT DISTINCT f.file_id, f.file_path, f.file_name
        FROM recent_item r
        JOIN file_info f ON r.file_id = f.file_id
        ORDER BY r.access_time DESC
    )";

	DbMgr::GetInstance()->executeSql(sql, [this, str](const DbResult& result) {
		if (!result.isSuccess()) {
			qWarning() << "获取文件列表失败:" << result.error();
			emit contentSearchCompleted(0, true);
			return;
		}

		QList<QPair<QUuid, int>> allResults;
		QMap<QUuid, QString> fileNames;
		QMap<QPair<QUuid, int>, QString> lineContents;

		// 遍历所有文件进行搜索
		for (const QVariantMap& row : result.data()) {
			QUuid fileId = QUuid(row["file_id"].toString());
			QString filePath = row["file_path"].toString();
			QString fileName = row["file_name"].toString();

			fileNames[fileId] = fileName;

			QList<int> matchedLines = searchInFile(filePath, str);
			for (int lineNum : matchedLines) {
				QPair<QUuid, int> key(fileId, lineNum);
				allResults.append(key);
				lineContents[key] = readLineContent(filePath, lineNum);
			}
		}

		int count = allResults.size();

		// 在主线程更新UI
		QMetaObject::invokeMethod(this, [this, allResults, fileNames, lineContents, count]() {
			if (m_searchResultList) {
				m_searchResultList->setMultiFileMode(allResults, fileNames, lineContents);
			}
			emit contentSearchCompleted(count, true);
			}, Qt::QueuedConnection);

		qDebug() << "多文件搜索完成，共找到" << count << "处匹配";
		});
}

void SearchService::onSearchTriggered(const QString& str, FindMode mode)
{
	if (mode == FindMode::CurrentItem) {
		searchInCurrentDoc(str);
	}
	else {
		searchInAllRecents(str);
	}
}

void SearchService::handleRecentSearchResult(const DbResult& result)
{
	if (!m_recentList) {
		qWarning() << "SearchService：处理结果时发现RecentList未设置";
		emit searchFailed("无法展示结果：未绑定RecentList");
		return;
	}

	// 清空原有结果
	m_recentList->clear();

	// 处理搜索失败
	if (!result.isSuccess()) {
		qWarning() << "SearchService：搜索失败" << result.error();
		emit searchFailed("搜索执行错误：" + result.error());
		showNotification(Notify_Type_Error, "搜索失败", "查询执行错误：" + result.error());
		return;
	}

	// 处理无结果场景
	QList<QVariantMap> resultData = result.data();
	if (resultData.isEmpty()) {
		qDebug() << "SearchService：搜索完成，无匹配结果";
		emit searchCompleted(0);
		showNotification(Notify_Type_Information, "搜索结果", "未找到匹配的最近访问记录");
		return;
	}

	// 处理有结果场景：转换为RecentItem并添加到列表
	qDebug() << "SearchService：搜索完成，匹配结果数：" << resultData.size();
	for (const QVariantMap& row : resultData) {
		// 提取核心字段
		QString fileName = row["file_name"].toString();
		QString filePath = row["file_path"].toString();
		QString accessTimeStr = row["access_time"].toString();
		QDateTime accessTime = QDateTime::fromString(accessTimeStr, Qt::ISODate);

		// 创建RecentItem并设置属性
		RecentItem* item = new RecentItem(fileName, accessTime);
		item->setFilePath(filePath);
		m_recentList->addItem(item);
	}

	// 发送搜索完成信号
	emit searchCompleted(resultData.size());
}

void SearchService::handleContentSearchResult(const DbResult& result, bool isAll)
{
	// 此方法可以保持空实现或移除
	// 实际的搜索逻辑已经在 searchInCurrentDoc 和 searchInAllRecents 中直接实现
	Q_UNUSED(result);
	Q_UNUSED(isAll);
}

void SearchService::showNotification(NotifyType type, const QString& title, const QString& content)
{
	if (!m_notification) {
		qWarning() << "SearchService::showNotification - Notification未设置";
		return;
	}

	// 使用右上角位置显示通知，存活时间3秒
	m_notification->Push(type, Pos_Top_Right, title, content, 3000);
}